#include <iostream>
#include <event2/event.h>
#ifndef _WIN32
#include <signal.h>
#endif
#include <thread> //c++自带的
using namespace std;

static  timeval t1 = {1,0};

static void timer1(int sock, short which, void *arg){
        cout<< "[timer1]"<<endl;

        event *ev = (event*)arg;
        //如果处于非待决状态
        if(!evtimer_pending(ev,&t1)){
                evtimer_del(ev);
                evtimer_add(ev,&t1);
        }
}
static void timer2(int sock, short which, void *arg){
        cout<< "[timer2]"<<endl;
        this_thread::sleep_for(3000ms); //c++11自带的
}
static void timer3(int sock, short which, void *arg){
        cout<< "[timer3]"<<endl;
}
int main(int argc, char const *argv[]){
#ifdef _WIN32
        //初始化socket库
        WSADATA wsa;
        WSAStartup(MAKEWORD(2,2), &wsa);
#else
        //忽略管道信号 发送数据给已关闭的socket
        if(signal(SIGPIPE,SIG_IGN) == SIG_IGN){
                return 1;
        }
#endif
        event_base *base = event_base_new();

        //定时器
        cout<<"test timer"<<endl;
        
        //evtimer_new只是对event_new进行了封装
        /*
        #define evtimer_assign(ev, b, cb, arg) \
	event_assign((ev), (b), -1, 0, (cb), (arg))
        #define evtimer_new(b, cb, arg)		event_new((b), -1, 0, (cb), (arg))
        #define evtimer_add(ev, tv)		event_add((ev), (tv))
        #define evtimer_del(ev)			event_del(ev)
        #define evtimer_pending(ev, tv)		event_pending((ev), EV_TIMEOUT, (tv))
        #define evtimer_initialized(ev)		event_initialized(ev)
        */
        event *ev1 = evtimer_new(base,timer1,event_self_cbarg()); //默认非持久的 只进入一次 需要手动每次添加

        evtimer_add(ev1, &t1); //插入性能O(logN)

        //设置持久事件 开放一般选择持久事件
        static timeval t2;
        t2.tv_sec = 1;
        t2.tv_usec = 200000;//微妙 

        event *ev2 = event_new(base, -1, EV_PERSIST, timer2, 0);
        event_add(ev2, &t2); //插入性能O(logN)
        
        //超时性能优化，默认event 用二叉堆存储(完全二叉树) 时间复杂度 插入删除 O(logN)
        //优化到双向队列 插入删除的时间复杂度 O(1)
        event *ev3 = event_new(base, -1, EV_PERSIST, timer3, 0);
        static timeval tv_in = {3, 0};
        const timeval *t3;
        t3 = event_base_init_common_timeout(base, &tv_in);
        event_add(ev3, t3); //插入性能O(1)

        
        event_base_dispatch(base);

        if(ev1)
                event_free(ev1);
        if(base)
                event_base_free(base);
        return 0;
}
//在网路通信时连接客户端时是不需要设置超时时间的
//但是在读取客户端连接的时候是需要设置超时的